package hd.util.http;

import android.support.annotation.NonNull;

import org.apache.http.*;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.entity.mime.FormBodyPart;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.impl.client.AbstractHttpClient;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicHeader;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;

import java.net.SocketTimeoutException;
import java.util.Arrays;
import java.util.List;

import hd.util.load.BaseLoader;

/**
 * HttpClient
 * 封装HttpClient
 * <p/>
 * Created by Haidy on 15/2/3.
 */
public class HttpClient {

    /**
     * 连接超时
     */
    public final static String ConnectTimeOut = "连接超时！";
    /**
     * 连接获取数据超时
     */
    public final static String SocketTimeOut = "获取数据超时！";
    /**
     * 网络异常
     */
    public final static String ConnectException = "网络异常！";
    /**
     * 连接失败
     */
    public final static String ConnectDefeated = "连接失败！";
    public final static String UnknownError = "未知错误";

    /**
     * 连接成功
     */
    public final static String OK = "ok";

    public static final String FAILURE = "failure";// 失败

    private org.apache.http.client.HttpClient httpClient;
    private int connectTimeOut = 30 * 1000;     //连接时间30s
    private int soTimeOut = 30 * 1000;          //获取数据的时间
    private int responseCode = 200;             //响应成功代码
    private String requestCharset = HTTP.UTF_8; //请求返回编码方式
    private String responseEncoding = HTTP.UTF_8;//请求返回编码

    public HttpClient() {
        httpClient = new DefaultHttpClient();
    }

//    /**
//     * 设置是否允许重定向
//     *
//     * @param redirect 是否允许
//     */
//    public void setRedirect(boolean redirect) {
//        this.redirect = redirect;
//    }

    /**
     * 请求回得编码
     *
     * @param responseEncoding encoding
     */
    public void setResponseEncoding(String responseEncoding) {
        this.responseEncoding = responseEncoding;
    }

    /**
     * 设置Post请求时候的数据编码方式
     *
     * @param requestCharset encoding
     */
    public void setRequestCharset(String requestCharset) {
        this.requestCharset = requestCharset;
    }

    /**
     * 获取连接超时时间
     *
     * @param connectTimeOut ContentTimeOut
     */
    public void setConnectTimeOut(int connectTimeOut) {
        this.connectTimeOut = connectTimeOut;
    }

    /**
     * 设置获取数据超时时间
     *
     * @param soTimeOut SoTimeOut
     */
    public void setSoTimeOut(int soTimeOut) {
        this.soTimeOut = soTimeOut;
    }

    /**
     * 设置响应成功应该返回的代码
     *
     * @param responseCode Code
     */
    public void setResponseCode(int responseCode) {
        this.responseCode = responseCode;
    }

    /**
     * Get请求
     *
     * @param url                 url
     * @param httpRequestListener 回调接口
     */
    public void httpGet(String url, HttpRequestListener httpRequestListener) {
        httpGet(url, (Header[]) null, httpRequestListener);
    }

    /**
     * Get 请求
     *
     * @param url      请求地址
     * @param cookie   cookie
     * @param listener 回调接口
     */
    public void httpGet(final String url, final String cookie, final HttpRequestListener listener) {
        httpGet(url, new Header[]{new BasicHeader("Cookie", cookie)}, listener);
    }

    /**
     * Get 请求
     *
     * @param url      请求地址
     * @param headers  请求头
     * @param listener 回调接口
     */
    public void httpGet(final String url, final Header[] headers, final HttpRequestListener listener) {
        BaseLoader.start(new BaseLoader.OnLoaderListener() {
            private boolean success = false;
            private HttpResponse response = new HttpResponse();

            @Override
            public void load() {
                setClientType();
                success = setRequest(new HttpGet(url), headers, response);
            }

            @Override
            public void finish() {
                if (success) {
                    listener.success(response);
                } else {
                    listener.failure(response);
                }
                listener.end();
            }
        });
    }

    /**
     * http post
     *
     * @param url      url
     * @param pairs    表单
     * @param listener 回调接口
     */
    public void httpPost(String url, List<FormBodyPart> pairs, HttpRequestListener listener) {
        httpPost(url, (Header[]) null, pairs, listener);
    }

    public void httpPost(final String url, final String cookie, final List<FormBodyPart> contentBodies, final HttpRequestListener listener) {
        httpPost(url, new Header[]{new BasicHeader("Cookie", cookie)}, contentBodies, listener);
    }

    /**
     * POST
     *
     * @param url      url
     * @param headers  请求头
     * @param listener 回调接口
     */
    public void httpPost(final String url, final Header[] headers, final List<FormBodyPart> bodyParts, final HttpRequestListener listener) {
        MultipartEntity multipartEntity = new MultipartEntity();
        for (FormBodyPart formBodyPart : bodyParts) {
            multipartEntity.addPart(formBodyPart);
        }
        httpPost(url, headers, multipartEntity, listener);
    }

    /**
     * post
     *
     * @param url                 url
     * @param headers             请求头
     * @param httpEntity          请求体
     * @param httpRequestListener 回调接口
     */
    public void httpPost(final String url, final Header[] headers, final HttpEntity httpEntity, @NonNull final HttpRequestListener httpRequestListener) {
        BaseLoader.start(new BaseLoader.OnLoaderListener() {
            private boolean success = false;
            private HttpResponse response = new HttpResponse();

            @Override
            public void load() {
                setClientType();
                HttpPost post = new HttpPost(url);
                post.setEntity(httpEntity);
                success = setRequest(post, headers, response);
            }

            @Override
            public void finish() {
                if (success) {
                    httpRequestListener.success(response);
                } else {
                    httpRequestListener.failure(response);
                }
                httpRequestListener.end();
            }
        });
    }

    /**
     * 请求
     *
     * @param request  httpRequest
     * @param headers  请求头
     * @param response 响应
     * @return 是否请求成功
     */
    private boolean setRequest(HttpRequestBase request, Header[] headers, HttpResponse response) {
        boolean success = false;
        try {
            request.setHeader(HTTP.CONN_DIRECTIVE, HTTP.CONN_KEEP_ALIVE);
            if (headers != null) {
                for (Header header : headers) {
                    request.setHeader(header.getName(), header.getValue());
                }
            }
            org.apache.http.HttpResponse httpResponse = httpClient.execute(request);
            response.responseCode = httpResponse.getStatusLine().getStatusCode();
            response.text = EntityUtils.toString(httpResponse.getEntity(), responseEncoding);
            response.cookies = ((AbstractHttpClient) httpClient).getCookieStore().getCookies();
            if (response.responseCode == responseCode) {
                success = true;
            } else {
                response.info = ConnectDefeated;
            }
            Header[] temp = httpResponse.getAllHeaders();
            if (headers != null) {
                response.headers = Arrays.asList(temp);
            }
        } catch (ConnectTimeoutException e) {// 连接超时抛出异常
            response.info = ConnectTimeOut;
        } catch (SocketTimeoutException e) {
            response.info = SocketTimeOut;
        } catch (Exception e) {
            response.info = ConnectException;
        } finally {
            httpClient.getConnectionManager().shutdown();
        }
        return success;
    }

    /**
     * 设置Client属性
     */
    private void setClientType() {
        httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, connectTimeOut);
        httpClient.getParams().setParameter(CoreConnectionPNames.SO_TIMEOUT, soTimeOut);
        httpClient.getParams().setParameter(CoreProtocolPNames.HTTP_CONTENT_CHARSET, HTTP.DEFAULT_CONTENT_CHARSET);
    }
}
